import {
    Body,
    Controller,
    Delete,
    FileTypeValidator,
    Get,
    MaxFileSizeValidator,
    Param,
    ParseFilePipe,
    ParseIntPipe,
    Patch,
    Post,
    Query,
    Req,
    UploadedFile,
    UseInterceptors
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";
import { ApiBearerAuth, ApiConsumes, ApiOperation, ApiTags } from "@nestjs/swagger";
import { Request } from "express";

import { AdminSystemRole } from "@/core/auth/constants";
import { RequireRoles } from "@/core/auth/decorator/require-roles.decorator";
import { MIMETypes } from "@/core/constant/global-enum";
import { ApiBaseResponse } from "@/core/decorators/api-base-response.decorator";
import { ApiPageResponse } from "@/core/decorators/api-page-response.decorator";
import AjaxResult from "@/core/utils/AjaxResult";

import { CreateFileDto } from "../file/dto/create-file.dto";
import { CreateSysUserDto } from "./dto/create-sys-user.dto";
import { QuerySysUserDto } from "./dto/query-sys-user.dto";
import { UpdatePasswordDto } from "./dto/update-password.dto";
import { UpdateSysUserDto } from "./dto/update-sys-user.dto";
import { UpdateSysUserProfileDto } from "./dto/update-sys-user-profile.dto";
import { SysUserService } from "./sys-user.service";
import { SysUserVo } from "./vo/sys-user.vo";

@ApiTags("管理员管理")
@ApiBearerAuth()
@Controller("/admin/user")
export class SysUserController {
    constructor(private readonly sysUserService: SysUserService) {}

    @ApiOperation({ summary: "管理员新增" })
    // @ApiCreatedResponse({ type: BaseSuccessResponseVO<SysUserVo> })
    @ApiBaseResponse(SysUserVo)
    @Post("/add")
    async create(@Body() createSysUserDto: CreateSysUserDto, @Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.create(createSysUserDto, req));
    }

    @ApiOperation({ summary: "管理员分页列表" })
    // @ApiResponse({ type: BaseSuccessResponseVO<PageResultVO<SysUserVo>> })
    @ApiPageResponse(SysUserVo)
    @Get("/page")
    async findListPage(@Query() querySysUserDto: QuerySysUserDto, @Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.findListPage(querySysUserDto, req));
    }

    @ApiOperation({ summary: "管理员列表" })
    @ApiBaseResponse({ type: "array", items: SysUserVo })
    @Get("/all")
    async findAll(@Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.findAll(req));
    }

    @ApiOperation({ summary: "登录用户详情", description: "查询当前登录用户的基本信息" })
    @ApiBaseResponse(SysUserVo)
    @Get("/self/userinfo")
    async findSelfUserInfo(@Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.findOne(req.user.id, req));
    }

    // @ApiOperation({ summary: "登录用户权限", description: "查询当前登录用户的菜单树和按钮权限列表" })
    // @Get("/self/menutree.permbtn")
    // async findSelfWithMenuTreeAndPermBtn(@Req() req: Request) {
    //     return AjaxResult.success(await this.sysUserService.findOneWithMenuTreeAndPermBtn(req.user.id));
    // }

    // @ApiOperation({ summary: "登录用户菜单树", description: "查询当前登录用户层级到按钮的完整菜单树" })
    // @Get("/self/menutree")
    // async findSelfMenuTree(@Req() req: Request) {
    //     return AjaxResult.success(await this.sysUserService.findFullMenuTree(req.user.id));
    // }

    // @ApiOperation({ summary: "管理员权限", description: "查询用户的菜单树和按钮权限列表" })
    // @Get(":id/menutree.permbtn")
    // async findOneWithMenuTreeAndPermBtn(@Param("id", ParseIntPipe) id: number) {
    //     return AjaxResult.success(await this.sysUserService.findOneWithMenuTreeAndPermBtn(id));
    // }

    @ApiOperation({ summary: "管理员详情" })
    @ApiBaseResponse(SysUserVo)
    @Get("/detail/:id")
    async findOne(@Param("id", ParseIntPipe) id: number, @Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.findOne(id, req));
    }

    @ApiOperation({ summary: "超级管理员设置", description: "设置管理系统超级管理员" })
    @RequireRoles(AdminSystemRole.SuperAdmin)
    @ApiBaseResponse(SysUserVo)
    @Patch(":id/set-super")
    async setSuperAdmin(@Param("id", ParseIntPipe) id: number, @Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.setSuperAdmin(id, req));
    }

    @ApiOperation({ summary: "密码修改", description: "更新管理系统用户自身密码" })
    @Patch("update/self/password")
    async updatePassword(@Body() updatePasswordDto: UpdatePasswordDto, @Req() req: Request) {
        return AjaxResult.success(
            await this.sysUserService.updatePassword(
                req.user.id,
                updatePasswordDto.oldPassword,
                updatePasswordDto.newPassword
            )
        );
    }

    @ApiOperation({ summary: "管理员编辑", description: "更新管理系统用户信息" })
    @ApiBaseResponse(SysUserVo)
    @Patch("/edit/:id")
    async update(
        @Param("id", ParseIntPipe) id: number,
        @Body() updateSysUserDto: UpdateSysUserDto,
        @Req() req: Request
    ) {
        return AjaxResult.success(await this.sysUserService.update(id, updateSysUserDto, req));
    }
    @ApiOperation({ summary: "个人信息编辑", description: "更新管理系统用户自身信息" })
    @ApiBaseResponse(SysUserVo)
    @Patch("/update/self/info")
    async updateSelf(@Body() updateSysUserProfileDto: UpdateSysUserProfileDto, @Req() req: Request) {
        return AjaxResult.success(await this.sysUserService.updateSelf(updateSysUserProfileDto, req));
    }

    @ApiOperation({ summary: "头像上传" })
    @ApiBaseResponse(SysUserVo)
    @ApiConsumes("multipart/form-data")
    @Post("/update/self/avatar")
    @UseInterceptors(FileInterceptor("file", { limits: { files: 1 } }))
    async uploadAvatar(
        @UploadedFile(
            new ParseFilePipe({
                validators: [
                    new MaxFileSizeValidator({ maxSize: 1024 * 1024 * 5 }),
                    new FileTypeValidator({ fileType: MIMETypes.ALL_IMAGE })
                ]
            })
        )
        file: Express.Multer.File,
        @Body() createFileDto: CreateFileDto,
        @Req() req: Request
    ) {
        return AjaxResult.success(await this.sysUserService.uploadAvatar(req, createFileDto, file));
    }

    @ApiOperation({ summary: "管理员删除" })
    @Delete("/delete/:id")
    async remove(@Param("id", ParseIntPipe) id: number) {
        return AjaxResult.success(await this.sysUserService.remove(id));
    }
}
